package yawning.mew.bear;

import yawning.mew.ProcEffect.Trigger;
import yawning.mew.character.CharacterModel.AttackResult;
import yawning.mew.sim.SimulationAction;
import yawning.mew.sim.SimulationEventAction;

public class PulverizeAction extends SimulationEventAction {
	BearThreatSimulator mState;
	private boolean mHasPulverize;
	private int mStacks;

	PulverizeAction(BearThreatSimulator state) {
		super(state.mSimEngine);

		mState = state;
		mHasPulverize = mState.mModel.mToon.getTalent(BearModel.PULVERIZE) > 0;
	}

	@Override
	public double perform() {
		int cost = mState.mModel.pulverizeCost;

		if (!mState.hasRage(cost) && !mState.mOoCEv.isUp()) return SimulationAction.ACTION_FAIL;
		if (!mHasPulverize || mState.mLacerateAction.getStacks() == 0) return SimulationAction.ACTION_FAIL;

		AttackResult result = mState.mModel.getFrontalYellowResult();

		if (result == AttackResult.MISS) {
			mNrPulverizeMiss++;

			if (mState.mIsLogging) mState.mLog.log("Pulverize: MISS\n");
		} else if (result == AttackResult.DODGE) {
			mNrPulverizeDodge++;

			if (mState.mIsLogging) mState.mLog.log("Pulverize: DODGE\n");
		} else if (result == AttackResult.PARRY) {
			mNrPulverizeParry++;

			if (mState.mIsLogging) mState.mLog.log("Pulverize: PARRY\n");
		} else {
			// Cancel the existing one so we can clean up the crit buff properly.
			if (isUp()) cancel();

			// 4.0.6 Pulverize is not affected by bonus weapon damage.
			mStacks = mState.mLacerateAction.getStacks();
			double damage = mState.mModel.getWeaponDamage(true) * mState.mModel.mLevelDep.getPulverizeMult() + mState.mModel.mLevelDep.getPulverizeDmg() * mStacks;

			if (result == AttackResult.CRIT) {
				mNrPulverizeCrit++;
				damage *= mState.mModel.multCrit;
			} else {
				mNrPulverizeHit++;
			}

			mState.mModel.addMeleeCrit(mStacks * 0.03);

			damage *= mState.getDirectDamageMult();
			mPulverizeDamage += Math.round(damage);

			if (mState.mIsLogging) mState.mLog.log("Pulverize: %s Damage: %d Crit Buff: +%d%%\n", result, Math.round(damage), mStacks * 3);

			mState.mLacerateAction.onPulverize();

			if (result == AttackResult.CRIT) {
				mState.mSavageDefenseEv.onTrigger();
				mState.mLotPEv.onTrigger();
				mState.mSimEngine.triggerProc(mState.mActiveTarget, Trigger.YELLOWCRIT);
			} else {
				mState.mSimEngine.triggerProc(mState.mActiveTarget, Trigger.YELLOW);
			}

			schedule(mState.mModel.basePulverizeBuffDuration + mState.mModel.lacPulverizeBuffDuration);
		}

		mState.onRageLoss(cost);

		if (result == AttackResult.CRIT) mState.onPrimalFuryTrigger();

		return 1.5;
	}

	@Override
	public void onExpire() {
		if (mState.mIsLogging) mState.mLog.log("Pulverize Expiration\n");

		mState.mModel.addMeleeCrit(-mStacks * 0.03);

		mStacks = 0;
	}

	boolean canPulverize() {
		return mState.mLacerateAction.getStacks() > 0 && mHasPulverize;
	}

	boolean hasPulverize() {
		return mHasPulverize;
	}

	int getStacks() {
		return mStacks;
	}

	long mPulverizeDamage = 0;
	int mNrPulverizeMiss = 0;
	int mNrPulverizeDodge = 0;
	int mNrPulverizeParry = 0;
	int mNrPulverizeCrit = 0;
	int mNrPulverizeHit = 0;
}
